package com.lengxf.pay.icbc.starter;

import com.lengxf.pay.common.enums.PayStatusEnum;
import com.lengxf.pay.common.service.BasePayService;
import com.lengxf.pay.icbc.ICBC_PayService;
import com.lengxf.pay.starter.parent.bean.PayBackResult;
import com.lengxf.pay.starter.parent.bean.QueryResult;
import com.lengxf.pay.starter.parent.bean.RefundQueryResult;
import com.lengxf.pay.starter.parent.bean.RefundResult;
import com.lengxf.pay.starter.parent.transfer.ResultTransfer;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

@Service
public class ICBC_ResultTransfer implements ResultTransfer {


    @Override
    public Class<? extends BasePayService> payType() {
        return ICBC_PayService.class;
    }

    @Override
    public PayBackResult payBackResultTransfer(Map<String, Object> data) {
        String code = String.valueOf(data.get("return_code"));
        String msg = String.valueOf(data.get("return_msg"));
        PayBackResult payBackResult = new PayBackResult(code, msg, "0".equals(code));
        if (payBackResult.getSuccess()) {
            payBackResult.setDateTime(LocalDateTime.now())
                    .setOrderNo(String.valueOf(data.get("out_trade_no")))
                    .setOutOrderNo(String.valueOf(data.get("order_id")))
                    .setAmount(new BigDecimal(String.valueOf(data.get("total_amt"))))
                    .setDateDay(getDateDay(String.valueOf(data.get("pay_time"))));
        }
        return payBackResult;
    }

    @Override
    public QueryResult queryResultTransfer(Map<String, Object> data) {
        String code = String.valueOf(data.get("return_code"));
        String msg = String.valueOf(data.get("return_msg"));
        QueryResult queryResult = new QueryResult(code, msg, "0".equals(code));
        if (queryResult.getSuccess()) {
            queryResult.setAmount(new BigDecimal(String.valueOf(data.get("total_amt"))))
                    .setDateDay(getDateDay(String.valueOf(data.get("pay_time"))))
                    .setDateTime(LocalDateTime.now())
                    .setOrderNo(String.valueOf(data.get("out_trade_no")))
                    .setOutOrderNo(String.valueOf(data.get("order_id")))
                    .setChannel(toChannelStr(String.valueOf(data.get("channel"))))
                    .setPayStatus(toPayStatusEnum(String.valueOf(data.get("pay_status"))));
        }
        return queryResult;
    }

    private static LocalDate getDateDay(String payTime) {
        try {
            return LocalDate.parse(payTime, DateTimeFormatter.ofPattern("yyyyMMdd"));
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public RefundQueryResult refundQueryResultTransfer(Map<String, Object> data) {
        String code = String.valueOf(data.get("return_code"));
        String msg = String.valueOf(data.get("return_msg"));
        RefundQueryResult refundQueryResult = new RefundQueryResult(code, msg, "0".equals(code));
        if (refundQueryResult.getSuccess()) {
            refundQueryResult.setRefundAmount(new BigDecimal(String.valueOf(data.get("reject_amt"))))
                    .setChannel(toChannelStr(String.valueOf(data.get("order_channel"))))
                    .setOrderNo(String.valueOf(data.get("out_trade_no")))
                    .setOutOrderNo(String.valueOf(data.get("order_id")))
                    .setRefundOrderNo(String.valueOf(data.get("reject_no")));
        }
        return refundQueryResult;
    }

    @Override
    public RefundResult refundResultTransfer(Map<String, Object> data) {
        String code = String.valueOf(data.get("return_code"));
        String msg = String.valueOf(data.get("return_msg"));
        RefundResult refundResult = new RefundResult(code, msg, "0".equals(code));
        if (refundResult.getSuccess()) {
            refundResult.setRefundOrderNo(String.valueOf(data.get("reject_no")))
                    .setOutRefundOrderNo(String.valueOf(data.get("trace_no")))
                    .setChannel(toChannelStr(String.valueOf(data.get("order_channel"))))
                    .setOrderNo(String.valueOf(data.get("out_trade_no")))
                    .setOutOrderNo(String.valueOf(data.get("order_id")))
                    .setRefundAmount(new BigDecimal(String.valueOf(data.get("real_reject_amt"))));
        }
        return refundResult;
    }


    private PayStatusEnum toPayStatusEnum(String payStatus) {
        //0：支付中请稍后查询，1：支付成功，2：支付失败，3：已撤销，4：撤销中请稍后查询，5：已全额退款，6：已部分退款，7：退款中请稍后查询
        return switch (payStatus) {
            case "0" -> PayStatusEnum.IN_PAY;
            case "1" -> PayStatusEnum.PAY_SUCCESS;
            case "2" -> PayStatusEnum.PAY_FAIL;
            case "3" -> PayStatusEnum.REVOKED;
            case "4" -> PayStatusEnum.IN_REVOKED;
            case "5" -> PayStatusEnum.FULL_REFUND;
            case "6" -> PayStatusEnum.REBATES;
            case "7" -> PayStatusEnum.IN_REFUND;
            default -> PayStatusEnum.OTHER;
        };
    }

    private String toChannelStr(String numStr) {
//        91-微信支付、92-支付宝、93-银联二维码、99-工银二维码、94-数字人民币
        return switch (numStr) {
            case "91" -> "微信支付";
            case "92" -> "支付宝";
            case "93" -> "银联二维码";
            case "99" -> "工银二维码";
            case "94" -> "数字人民币";
            default -> "未知类型";
        };
    }

}
